package com.jf.anmocker.plugin.asmfactory

import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.jf.anmocker.plugin.mockcore.asm.AnMockerClzNode
import groovyjarjarasm.asm.Opcodes
import org.objectweb.asm.ClassVisitor

/**
 * @Class: MyTransformFactory
 * @Description:
 * @author:
 * @Date: 2022/9/21
 */
abstract class AMTransformFactory : AsmClassVisitorFactory<AnMockerParams> {

    companion object{
        var showNoFilterMsg = false
    }

    init {
        //println("--AMTransformFactory init : $this --")
    }

    //必须实现 createClassVisitor 所以我们先创建 ClassVisitor
    override fun createClassVisitor(classContext: ClassContext, nextClassVisitor: ClassVisitor): ClassVisitor {
        return AnMockerClzNode(Opcodes.ASM9, nextVisitor = nextClassVisitor)
        //return AnMockerClzVisitor(Opcodes.ASM6, nextVisitor = nextClassVisitor)
    }

    //这个方法是判断当前类是否要进行扫描，因为如果所有类都要通过ClassVisitor进行扫描还是太耗时了.
    //我们可以通过这个方法过滤掉很多我们不需要扫描的类
    override fun isInstrumentable(classData: ClassData): Boolean {
        val regexResourceClass = """(\w*(.\w*))*.R(\$\w*)?""".toRegex()
        if(regexResourceClass.matches(classData.className)){
            //resourceFile 直接忽略
            return false
        }else{
            val list : List<String>? = parameters.get().packages
            if(list !=null && list.isNotEmpty()){
                for(item in list){
                    val regexUserPath = """${item}.(\w*(.\w*))*.\w?""".toRegex()
                    if(regexUserPath.matches(classData.className)){
                        //println("target class filter by package >>> ${classData.className}")
                        return true
                    }
                }
                return false
            }else{
                if(!showNoFilterMsg){
                    println("----------target class scan with no package filter----------")
                    showNoFilterMsg = true
                }
                return true
            }
        }
    }

    public fun showMsg(msg : String?){
        msg?.let {
            println(it)
        }
    }
}